package model

import (
	"encoding/json"
	"io"
	"strconv"
	"time"

	"github.com/pkg/errors"
)

type contextKey struct {
	key string
}

// TimeDuration repesents duration of time
type TimeDuration time.Duration

// TimeSecond is same as time.Second
const TimeSecond TimeDuration = TimeDuration(time.Second)

// JSON represents json
type JSON string

// CharacterData repesents character resource
type CharacterData struct {
	ID     int    `json:"id"`
	ImgURL string `json:"imgUrl"`
}

// NewCharacterData creates Character
func NewCharacterData() *CharacterData {
	return &CharacterData{
		ImgURL: "https://example.com",
	}
}

// UnmarshalGQL implements the graphql.Unmarshaler interface
func (t *TimeDuration) UnmarshalGQL(v interface{}) error {
	ti, ok := v.(json.Number)
	if !ok {
		return errors.New("time must be json.Number")
	}
	num, err := ti.Int64()

	if err != nil {
		return errors.Wrapf(err, "UnmarshGQL: Time: %v", num)
	}

	*t = TimeDuration(num)
	return nil
}

// MarshalGQL implements the graphql.Marshaler interface
func (t TimeDuration) MarshalGQL(w io.Writer) {
	io.WriteString(w, strconv.FormatInt(int64(t), 10))
}

// UnmarshalGQL implements the graphql.Unmarshaler interface
func (j *JSON) UnmarshalGQL(v interface{}) error {
	data, ok := v.(string)
	if !ok {
		return errors.New("JSON must be string")
	}
	*j = JSON(data)
	return nil
}

// MarshalGQL implements the graphql.Marshaler interface
func (j JSON) MarshalGQL(w io.Writer) {
	io.WriteString(w, string(j))
}
